package com.pengpeng.jjwt.utils;

import com.pengpeng.jjwt.constants.JwtConstant;
import com.pengpeng.jjwt.entity.JwtParam;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.util.Date;
import java.util.Map;

/**
 * @author pengp
 * @date 2022年03月03日 11:07
 */
@Slf4j
public class JwtUtils {
    private static final String AUTHORIZATION_HEADER_PREFIX="Bearer ";
    private JwtUtils(){}

    /**
     * 获取token
     * @Author pengp
     * @Date 2022/3/3 15:32
     * @param authorizationHeader 原请求头
     * @return java.lang.String
     */
    public static String getRawToken(String authorizationHeader) {
        return authorizationHeader.substring(AUTHORIZATION_HEADER_PREFIX.length());
    }

    public static String getAuthorizationHeader(String rawToken){
        return AUTHORIZATION_HEADER_PREFIX + rawToken;
    }

    public static boolean validate(String authorizationHeader){
        return StringUtils.hasText(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_HEADER_PREFIX);
    }

    public static String createToken(String userId, JwtParam jwtParam){
        return createToken(userId,null,jwtParam);
    }

    private static String createToken(String userId, Map<String, Object> claim, JwtParam jwtParam) {
        try {
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

            long nowMillis = System.currentTimeMillis();
            Date now = new Date(nowMillis);

            byte[] apiKeeySecretBytes = DatatypeConverter.parseBase64Binary(jwtParam.getBase64Secret());
            SecretKeySpec secretKeySpec = new SecretKeySpec(apiKeeySecretBytes,signatureAlgorithm.getJcaName());

            JwtBuilder jwtBuilder = Jwts.builder().setHeaderParam("typ","JWT")
                    .claim(JwtConstant.USER_ID_KEY,userId)
                    .addClaims(claim)
                    .setIssuer(jwtParam.getName())
                    .setIssuedAt(now)
                    .signWith(signatureAlgorithm,secretKeySpec);

            long ttlMillis = jwtParam.getJwtExpires() * 60 * 1000;
            if(ttlMillis >= 0){
                long expMillis = nowMillis + ttlMillis;
                Date exp = new Date(expMillis);
                jwtBuilder.setExpiration(exp);
            }
            return jwtBuilder.compact();
        } catch (Exception e){
            log.error("签名失败",e);
            return null;
        }
    }

    public static Claims parseToken(String authToken,String base64Secret){
        try{
            Claims claims = Jwts.parser().setSigningKey(base64Secret).parseClaimsJws(authToken).getBody();
            return claims;
        }catch (SignatureException se){
            log.error("======= 秘钥不匹配 =========",se);
        }catch (ExpiredJwtException ejw){
            log.error("======= token过期 =========",ejw);
        }catch (Exception e){
            log.error("======= token解析异常 =====",e);
        }
        return null;
    }


}
